/*
 * ZBrowser is an embeddable browser component.
 * Copyright (C) Author: Gangadhar Nagesh Metla (Novell, Inc.)
 * nmetla74@gmail.com 
 * Version 1.0
 * 1/3/2009
 * Filename ZBrowser.java
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.novell.zenworks.agent.zbrowser;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

import org.lobobrowser.gui.BrowserPanel;
import org.lobobrowser.main.PlatformInit;
import org.lobobrowser.ua.NavigationEvent;
import org.lobobrowser.ua.NavigationListener;
import org.lobobrowser.ua.NavigationVetoException;

import com.novell.zenworks.agent.common.ICommonUIEnums.MB_ICON;
import com.novell.zenworks.agent.common.ICommonUIEnums.MB_RESPONSE;
import com.novell.zenworks.agent.common.ICommonUIEnums.MB_TYPE;
import com.novell.zenworks.agent.zbrowser.cmddialogs.BundlePropDialog;
import com.novell.zenworks.zicon.common.dialogs.IBundlePropData;
import com.novell.zenworks.zicon.common.HTMLPage;
import com.novell.zenworks.zicon.common.LogUtil;
import com.novell.zenworks.zicon.common.ResourceManager;

/**
 * Z Embeddable Browser.
 */
public class ZBrowser extends JFrame
{
    private static final long      serialVersionUID = 1L;
    private BrowserPanel           browserPanel;
    private String                 protocol;
    private String                 host;
    private int                    port;
    private static String          applicationResourcePath; //path for application's resources.
    private String                 applicationTitle;
    private HTMLPage               page;
    private int                    applicationTimeout;
    public static final ResourceManager rm = ResourceManager.getInstance();
    private static Map<String, BundlePropDialog> propDlgMap = new HashMap<String, BundlePropDialog>();

    public ZBrowser(BrowserPanel browserPanel, String applicationResPath, String applicationTitle, String protocol, String host, int port, String homePageId, String pageType, int timeout) throws Exception
    {
    	super();
    	this.setName(pageType);
        initializePlatform();
        applicationResourcePath = applicationResPath;
        this.applicationTitle = applicationTitle;
        this.protocol = protocol;
        this.host = host;
        this.port = port;
        if (browserPanel != null)
        {
            this.browserPanel = browserPanel;
        } else
        {
            this.browserPanel = new BrowserPanel(null, false, false, false);
        }
        this.page = new HTMLPage(homePageId, homePageId, pageType);
        this.applicationTimeout = timeout;
        this.getContentPane().add(this.browserPanel);
        this.initialize();
        this.closeOntimeout();
    }
    
    private void closeOntimeout()
    {
        if(applicationTimeout > 0)
        {
            Timer t = new Timer();
            t.schedule(new ApplicationDisposer(this), applicationTimeout * 1000);    
        }        
    }

    private void initializePlatform() throws Exception
    {
        PlatformInit.getInstance().initLogging(false);
        PlatformInit.getInstance().initConsole();
        PlatformInit.getInstance().initOtherProperties();
        PlatformInit.getInstance().initExtensions();
    }

    public void initialize() throws Exception
    {
        setDefaultURL();
        addEventListeners();
        initializeApplicationDefaults();
    }

    public void initializeApplicationDefaults() throws Exception
    {
    	if(this.getName().equalsIgnoreCase("dataform"))
        {
    		this.setResizable(false);
    		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        }
    	else
    	{
    		this.setResizable(true);
            this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    	}
        this.setSize(800, 775);
        this.setTitle(applicationTitle);
        
        if(!System.getProperty("os.name").toLowerCase().contains("mac"))
        {
        	String titleImage =  getIconPath() + File.separator + "Application.png";
        	ImageIcon titleIcon = new ImageIcon(titleImage);
        	((JFrame)this).setIconImage(titleIcon.getImage());
        }
        
        this.setEnabled(true);
        this.setVisible(true);
    }

    public void setDefaultURL() throws Exception
    {
        ZURLStreamHandlerFactory factory = new ZURLStreamHandlerFactory(page);
        URL url = new URL(protocol, host, port, "file://" + applicationResourcePath, factory.createURLStreamHandler(protocol));
        browserPanel.navigate(url);
    }
    
    public static String getIconPath() throws Exception
    {
        String path = null;
        String osName = System.getProperty("os.name");
        if(osName.toLowerCase().contains("mac"))
        {
            path =  applicationResourcePath + File.separator + "zicon" + File.separator + "mac";
        }
        else //use linux images for other platforms until there is a platform specific requirement.
        {
            path = applicationResourcePath + File.separator + "zicon" + File.separator + "linux";
        }
        return path;
    }

    public void addEventListeners()
    {
        browserPanel.addNavigationListener(new NavigationListener()
        {

            public void beforeLocalNavigate(NavigationEvent arg0) throws NavigationVetoException
            {
                String resourcePath = "file://" + applicationResourcePath + "?";
                try
                {
                    if(arg0.getURL() != null)
                    {
                        if(arg0.getURL().getAuthority() != null && arg0.getURL().getAuthority().equalsIgnoreCase("help")) //for launching files such as help etc.,
                        {
                            Class cl = Class.forName("com.novell.zenworks.agent.zicon.ZTrayIcon");
                            Class[] par= new Class[1];
                            par[0]=String.class;
                            Method mthd=cl.getMethod("launchHelpFile", par);
                            Integer output=(Integer)mthd.invoke(cl, "file://"+arg0.getURL().getFile());                  
                        }
                        if(arg0.getURL().getAuthority() != null && arg0.getURL().getAuthority().equalsIgnoreCase("refresh")) //for refreshing page
                        {
                            refreshPage();                  
                        }
                        else
                        {
                            NavigationUtils.NavigateTo(arg0, resourcePath, page, browserPanel, (JFrame) getFrames()[0]);
                        }
                    }
                } catch (Throwable e) {
                	try
                    {
                        String errMsg = e.getMessage();
                        if(errMsg != null) {
                            LogUtil.LogException(errMsg, e);
                        	String rmiStr = "java.rmi.RemoteException";
                        	if(errMsg.contains(rmiStr)) {
                        		int lastIndex = errMsg.lastIndexOf(rmiStr);
                        		errMsg = errMsg.substring(lastIndex + rmiStr.length() + 1);
                        	}
                        	MessageBoxLauncher.ShowMessageBoxHandler(errMsg, "ZENworks Adaptive Agent" , MB_TYPE.MBT_OK, MB_ICON.MBI_ERROR, 30, false, MB_RESPONSE.MBR_OK);
                        }
                        else
                        {
                            MessageBoxLauncher.ShowMessageBoxHandler("RemotingError", "ZENworks Adaptive Agent" , MB_TYPE.MBT_OK, MB_ICON.MBI_ERROR, 30, false, MB_RESPONSE.MBR_OK);
                        }

                    } catch (Exception e1)
                    {
                        LogUtil.LogException(e.getMessage(), e1);
                    }
                    throw new NavigationVetoException(e.getMessage());
                }
            }

            public void beforeNavigate(NavigationEvent arg0) throws NavigationVetoException
            {
            }

            public void beforeWindowOpen(NavigationEvent arg0) throws NavigationVetoException
            {
            }
        });
        
        this.addWindowListener(new WindowListener()
        {

            public void windowActivated(WindowEvent e)
            {
                
            }

            public void windowClosed(WindowEvent e)
            {
                // TODO Auto-generated method stub
                
            }

            @SuppressWarnings("unchecked")
            public void windowClosing(WindowEvent e)
            {
                Class cl;
                try
                {
                    String browserName = e.getWindow().getName();
                    if(browserName != null && browserName.equalsIgnoreCase("property"))
                    {
                        cl = Class.forName("com.novell.zenworks.agent.zicon.PageApp");
                        Method mthd=cl.getMethod("nullifyBrowser");
                        Integer output=(Integer)mthd.invoke(cl); 
                        e.getWindow().dispose();
                    }
                    
                } catch (Exception e1)
                {
                    LogUtil.LogException(e1.getMessage(), e1);
                }            
            }

            public void windowDeactivated(WindowEvent e)
            {
                // TODO Auto-generated method stub
                
            }

            public void windowDeiconified(WindowEvent e)
            {     
            }

            public void windowIconified(WindowEvent e)
            {
                
            }

            public void windowOpened(WindowEvent e)
            {
            }
            
        });
    }
    
    

    public void unIconify()
    {
        this.toFront();    
    }    

    public String getProtocol()
    {
        return protocol;
    }

    public void setProtocol(String protocol)
    {
        this.protocol = protocol;
    }

    public String getHost()
    {
        return host;
    }

    public void setHost(String host)
    {
        this.host = host;
    }

    public int getPort()
    {
        return port;
    }

    public void setPort(int port)
    {
        this.port = port;
    }

    public static String getApplicationResourcePath()
    {
        return applicationResourcePath;
    }

    public String getApplicationTitle()
    {
        return applicationTitle;
    }

    public void setApplicationTitle(String applicationTitle)
    {
        this.applicationTitle = applicationTitle;
    }

    public static long getSerialVersionUID()
    {
        return serialVersionUID;
    }

    public BrowserPanel getBrowserPanel()
    {
        return browserPanel;
    }

    public void setBrowserPanel(BrowserPanel browserPanel)
    {
        this.browserPanel = browserPanel;
    }

    public HTMLPage getPage()
    {
        return page;
    }

    public void setPage(HTMLPage page)
    {
        this.page = page;
    }
    
    public void refreshPage() throws Exception
    {
        ZURLStreamHandlerFactory factory = new ZURLStreamHandlerFactory(page);
        URL url = new URL(protocol, host, port, "file://" + applicationResourcePath, factory.createURLStreamHandler(protocol));
        browserPanel.navigate(url);
    }

	public static void launchBundlePropertiesDialog(JFrame frame, IBundlePropData data) throws RemoteException 
	{
		if(!propDlgMap.containsKey(data.getGuid()))
		{
			BundlePropDialog dlg = new BundlePropDialog(frame, data);
			propDlgMap.put(data.getGuid(), dlg);
			dlg.setTitle(data.getTitle());
			dlg.setSize(550, 480);
			dlg.setResizable(false);
			dlg.setModal(false);
			dlg.setVisible(true);
			dlg.requestFocusOnOkButton();
			dlg.setBundleIcon(data.getIconPath());
		}
		else
		{
			BundlePropDialog dlg = propDlgMap.get(data.getGuid());
			dlg.toFront();
		}
	}
	
	public static void removeBundlePropertiesDialogEntry(String guid)
	{
        propDlgMap.remove(guid);
	}
}